﻿#include "ZShell.h"

#include <memory>
#include <iostream>
#include "../Driver/ZUartDriver.h"
#include "shell_port.h"

ZShell::ZShell(uint32_t UART_DEVICE_ID, uint32_t INTC_DEVICE_ID,
               uint32_t UART_INT_IRQ_ID) {
  zUartDriver_ = std::make_shared<ZUartDriver>(
      UART_DEVICE_ID,
      INTC_DEVICE_ID,
      UART_INT_IRQ_ID,
      [](void *call_back_ref) {
        auto uart_instance_ptr = (XUartPs *) call_back_ref;

        // 读取中断ID寄存器，判断触发的是哪种中断
        auto isr_status = XUartPs_ReadReg(uart_instance_ptr->Config.BaseAddress,
                                          XUARTPS_IMR_OFFSET);
        isr_status &= XUartPs_ReadReg(uart_instance_ptr->Config.BaseAddress,
                                      XUARTPS_ISR_OFFSET);

        // 数据存储buffer
        static uint8_t tempReceiveData[1024];
        // 尝试记录数据
        auto recvDataFunc = [=] {
          auto recSize = XUartPs_Recv(uart_instance_ptr, tempReceiveData,
                                      sizeof(tempReceiveData));
          lwrb_write(ShellReadBufferHandle(), tempReceiveData, recSize);
        };
        // 判断中断标志位RxFIFO是否触发
        if (isr_status & (u32) XUARTPS_IXR_RXOVR) {
          recvDataFunc();
          //清除中断标志
          XUartPs_WriteReg(uart_instance_ptr->Config.BaseAddress,
                           XUARTPS_ISR_OFFSET,
                           XUARTPS_IXR_RXOVR);
        } else if (isr_status & (u32) XUARTPS_IXR_TOUT) {
          recvDataFunc();
          //清除中断标志
          XUartPs_WriteReg(uart_instance_ptr->Config.BaseAddress,
                           XUARTPS_ISR_OFFSET,
                           XUARTPS_IXR_TOUT);
        }
      }
      );

  // 初始化shell
  userShellInit();
}

ZShell::~ZShell() {
}

void ZShell::runOnce() const {
  shellTask(&shell);

  // 数据缓存
  static uint8_t tempBuffer[1024];
  // 查看当前的数据长度
  const auto tempSize = lwrb_get_full(ShellWriteBufferHandle());
  if (tempSize > 0) {
    // 读取数据
    auto readSize = lwrb_read(ShellWriteBufferHandle(), tempBuffer, tempSize);
    if (readSize != tempSize) {
      std::cerr << "read size mismatch" << std::endl;
    }
    // 写入串口
    zUartDriver_->write(tempBuffer, readSize);
  }
}